Micron Document
πŸŽ–οΈGitΠ―Ρ€Π°πŸŽ–οΈ


Displaying Rendered β€’ View raw β€’ Download

specs/20260520-153449-node-list-context-menu/spec.md bd2863243bab6eb213401d949839a2bc74dde7e2 (bd286324) Text, 9.66 KB

Feature Specification: Node List Context Menu Alignment

Feature Branch: T383838jamesarich/issue-5544-alignment-align-node-list-long-press-co-1d63b1
Created: 2025-05-20
Status: Draft
Input: GitHub Issue #5544 β€” Align node list long-press context menu to canonical order
Cross-Platform Spec: Menu Alignment Audit (cross-platform canonical order)

Summary

The node list long-press context menu currently shows 4 items (Favorite, Mute, Ignore, Remove) in a non-standard order. This feature aligns the context menu to the cross-platform canonical order by reordering existing items, renaming "Mute Always" to "Mute notifications", and adding two new actions ("Message" and "Trace Route") for a total of 6 menu items. This improves cross-platform consistency and provides quick access to frequently used node actions.

Goals

1. Match the cross-platform canonical menu order exactly as defined in the Menu Alignment Audit
2. Add "Message" action to the context menu so users can quickly start a conversation with a node
3. Add "Trace Route" action to the context menu so users can diagnose connectivity without navigating away
4. Rename "Mute Always" to "Mute notifications" for clearer, user-friendly labeling
5. Maintain consistent behavior across Android and Desktop adaptive node list screens

Clarifications

Session 2026-05-20

β€’ Q: Should the context menu appear for the local node (self) on long-press? β†’ A: Suppress context menu entirely for the local node (no menu on long-press of self)

Non-Goals

β€’ Redesigning the visual appearance of the dropdown menu (colors, typography, spacing)
β€’ Adding new functionality behind the "Message" or "Trace Route" actions β€” these wire to existing capabilities
β€’ Changing context menu behavior on the map view or other screens
β€’ Modifying the underlying favorite/ignore/mute/remove logic

User Scenarios & Testing (mandatory)

User Story 1 - Canonical Menu Order (Priority: P1)

A user long-presses a node in the node list and sees all 6 context menu items in the expected canonical order, matching other Meshtastic platforms.

Why this priority: Core requirement β€” the entire feature is about establishing the correct menu order for cross-platform consistency.

Independent Test: Long-press any node in the node list and verify the menu displays exactly 6 items in the specified order.

Acceptance Scenarios:

1. Given a node list with at least one node, When the user long-presses a node, Then the context menu displays items in this order: (1) Add to favorites / Remove from favorites, (2) Mute notifications / Unmute, (3) Message, (4) Trace Route, (5) Ignore / Remove from ignored, (6) Remove
2. Given a node that cannot be muted (canMuteNode is false), When the user long-presses the node, Then "Mute notifications" is hidden but all other items remain in their canonical positions


User Story 2 - Message Action (Priority: P2)

A user long-presses a node and selects "Message" to navigate directly to a conversation with that node.

Why this priority: Adds a frequently needed shortcut β€” messaging is a primary use case in Meshtastic.

Independent Test: Long-press a node, tap "Message", and verify navigation to the messaging screen for that node.

Acceptance Scenarios:

1. Given a node in the node list, When the user long-presses and selects "Message", Then the app navigates to the direct message conversation with that node
2. Given an ignored node, When the user long-presses the node, Then the "Message" action is disabled (consistent with other actions on ignored nodes)


User Story 3 - Trace Route Action (Priority: P2)

A user long-presses a node and selects "Trace Route" to initiate route tracing to that node.

Why this priority: Provides quick access to a diagnostic action without navigating to node details.

Independent Test: Long-press a node, tap "Trace Route", and verify the trace route operation is initiated.

Acceptance Scenarios:

1. Given a node in the node list, When the user long-presses and selects "Trace Route", Then a trace route request is initiated to that node
2. Given an ignored node, When the user long-presses the node, Then the "Trace Route" action is disabled


User Story 4 - Mute Notifications Rename (Priority: P3)

The mute action displays "Mute notifications" instead of the previous "Mute Always" label.

Why this priority: Label improvement for clarity β€” lower priority since functionality is unchanged.

Independent Test: Long-press a node that supports muting and verify the label reads "Mute notifications" (not "Mute Always").

Acceptance Scenarios:

1. Given a node that can be muted and is not currently muted, When the user long-presses the node, Then the menu shows "Mute notifications" (not "Mute Always")
2. Given a node that is currently muted, When the user long-presses the node, Then the menu shows "Unmute" (unchanged)


Edge Cases

β€’ What happens when the user long-presses the local node (self)? The context menu MUST NOT appear β€” long-press on self is a no-op.
β€’ What happens if the node disappears from the mesh while the context menu is open? The menu should dismiss gracefully.
β€’ What happens when "Message" is selected for a node with no prior conversation? A new conversation should be created.

Architecture

Key Components

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Component β”‚ Module / File β”‚ Purpose β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ NodeContextMenu β”‚ T383838feature/node/component/NodeContextMenu.kt β”‚ Shared context menu composable —… β”‚
β”‚ NodeListScreen β”‚ T383838feature/node/list/NodeListScreen.kt β”‚ Wires context menu callbacks inc… β”‚
β”‚ String Resources β”‚ T383838core/resources/.../strings.xml β”‚ Add "mutenotifications", "messag… β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Requirements (mandatory)

Functional Requirements

β€’ FR-001: Context menu MUST display exactly 6 items in canonical order: Favorite, Mute notifications, Message, Trace Route, Ignore, Remove
β€’ FR-002: "Mute Always" string MUST be renamed to "Mute notifications" across the app
β€’ FR-003: "Message" menu item MUST navigate the user to the direct message screen for the selected node
β€’ FR-004: "Trace Route" menu item MUST initiate a trace route request to the selected node
β€’ FR-005: "Ignore" MUST appear at position 5 (before Remove)
β€’ FR-006: "Remove" MUST appear at position 6 (last item in the menu)
β€’ FR-007: "Message" and "Trace Route" MUST be disabled for ignored nodes (consistent with Favorite behavior)
β€’ FR-008: "Mute notifications" item MUST remain conditionally visible based on node's canMuteNode capability
β€’ FR-009: Context menu MUST NOT appear when the user long-presses the local node (self)

Non-Functional Requirements

β€’ NFR-001: Context menu MUST appear within 300ms of long-press to maintain responsive feel
β€’ NFR-002: All new menu items MUST have proper accessibility labels for TalkBack/screen readers
β€’ NFR-003: Menu MUST work identically on both Android and Desktop adaptive screens

Source-Set Impact

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Source Set β”‚ Impact β”‚ Justification β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ T383838commonMain β”‚ Modified: NodeContextMenu.k… β”‚ All business logic and UI per Constitution Β§I, Β§III β”‚
β”‚ T383838androidMain β”‚ None β”‚ No platform-specific changes needed β”‚
β”‚ T383838jvmMain β”‚ None β”‚ No platform-specific changes needed β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Design Standards Compliance

β€’ [ ] New screens reviewed against design standards
β€’ [ ] M3 component selection verified (DropdownMenuItem with leadingIcon pattern maintained)
β€’ [ ] Accessibility: TalkBack semantics on new menu items, touch targets adequate
β€’ [ ] Typography: Consistent with existing menu item text styling

Privacy Assessment

β€’ [ ] No PII, location data, or cryptographic keys logged or exposed
β€’ [ ] No new network calls that transmit user data
β€’ [ ] Proto submodule (T383838core/proto) not modified (read-only upstream)

Success Criteria (mandatory)

Measurable Outcomes

β€’ SC-001: Context menu displays exactly 6 items in the canonical order on 100% of long-press interactions
β€’ SC-002: Users can reach "Message" for any node in 1 long-press + 1 tap (vs. previous multi-step navigation)
β€’ SC-003: Users can initiate "Trace Route" for any node in 1 long-press + 1 tap (vs. previous multi-step navigation)
β€’ SC-004: No regressions in existing Favorite, Mute, Ignore, and Remove functionality
β€’ SC-005: Menu label reads "Mute notifications" in all locales where translation is available

Assumptions

β€’ All business logic and UI composables reside in T383838commonMain source set
β€’ String resources added to T383838core/resources/src/commonMain/composeResources/values/strings.xml
β€’ Icons use T383838MeshtasticIcons (from T383838core/ui/icon/) β€” suitable icons exist or will be added for Message and Trace Route
β€’ The existing "Message" navigation and "Trace Route" request functionality already exists in the app and only needs to be wired into the context menu
β€’ The Menu Alignment Audit canonical order is the authoritative source for item positioning
β€’ "Mute notifications" / "Unmute" toggle logic remains identical to current "Mute Always" / "Unmute" behavior
β€’ Disabled state for ignored nodes applies to Message and Trace Route (matching existing Favorite disabled behavior)

Served by rngit 1.5.0 - Generated in 0.04s